/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package checkers.web;

import checkers.constants.web.WebPages;
import checkers.businessLogic.GameManager;
import checkers.exceptions.EmailNotUniqueException;
import checkers.businessLogic.UserManager;
import checkers.businessLogic.entity.User;
import checkers.constants.freemarker.Tags;
import checkers.constants.messages.AuthenticationMessages;
import checkers.constants.messages.GameMessages;
import checkers.constants.web.SessionAttributes;
import com.google.gson.Gson;
import freemarker.template.Configuration;
import java.sql.Date;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

/**
 *
 * @author artinshahverdian
 */
public class UserOperationsViewGenerator {

    private Configuration configuration = null;
    private UserManager userManager = null;
    private GameManager gameManager = null;

    public UserOperationsViewGenerator(final Configuration configuration) throws Exception {

        this.configuration = configuration;

        userManager = UserManager.getInstance();

        gameManager = GameManager.getInstance();


    }

    public View forwardHome(HttpServletRequest request, boolean tableCreationError) throws SQLException {

        Map map = new HashMap();

        String name = null;
        String email = null;
        if (!hasSession(request)) {

            map.put(Tags.NAME, SessionAttributes.GUEST_ID);
            map.put(Tags.EMAIL, SessionAttributes.GUEST_ID);
            map.put(Tags.GAME_TABLE_CREATION_ERROR, "");

        }
        else {
            String userId = getSessionUserId(request);

            if (isGuestId(userId)) {
                name = SessionAttributes.GUEST_ID;
                email = SessionAttributes.GUEST_ID;
            }
            else {

                name = userManager.getNameFromUserId(userId);
                email = userManager.getEmailFromUserId(userId);
            }


            map.put(Tags.EMAIL, email);
            map.put(Tags.NAME, name);
            if (tableCreationError)
                map.put(Tags.GAME_TABLE_CREATION_ERROR, GameMessages.GAME_CREATION_ERROR);
            else
                map.put(Tags.GAME_TABLE_CREATION_ERROR, "");

        }

        return new View(map, WebPages.HOME, configuration);


    }

    public View forwardLogin(HttpServletRequest request, boolean loginError) throws SQLException {

        Map map = new HashMap();
        if (!hasSession(request)) {
            if (!loginError) {

                map.put(Tags.LOGIN_ERROR, "");


            }
            else {
                map.put(Tags.LOGIN_ERROR, AuthenticationMessages.LOGIN_ERROR);
            }
            return new View(map, WebPages.LOGIN, configuration);
        }
        else
            return forwardHome(request, false);
    }

    public View forwardRegister(HttpServletRequest request) throws SQLException {

        if (!hasSession(request)) {
            Map map = new HashMap();

            map.put(Tags.REGISTRATION_ERROR, "");

            return new View(map, WebPages.REGISTER, configuration);
        }
        else {
            return forwardHome(request, false);
        }
    }

    public boolean login(String email, String password, HttpServletRequest request) throws SQLException {

        User user = userManager.login(email, password);
        boolean success = false;
        if (user != null)
            success = true;


        if (success) {

            createSession(request, new Integer(user.getId()).toString());
            return true;
        }
        else {
            Map map = new HashMap();
            map.put(Tags.LOGIN_ERROR, AuthenticationMessages.LOGIN_ERROR);
            return false;
        }





    }

    public View register(String email, String password, String firstName, String lastName, Date birthdate,
            String securityQuestion, String securityAnswer) throws SQLException {
        Map map = new HashMap();
        try {
            try {
                userManager.register(email, password, firstName, lastName,
                        birthdate, securityQuestion, securityAnswer);

                map.put(Tags.REGISTRATION_STATUS, AuthenticationMessages.SUCCESSFULY_REGISTERED);
                return new View(map, WebPages.REGISTERED, configuration);
            }
            catch (EmailNotUniqueException ex) {
                Logger.getLogger(UserOperationsViewGenerator.class.getName()).log(Level.SEVERE, null, ex);
                map.put(Tags.REGISTRATION_ERROR, AuthenticationMessages.REGISTRATION_ERROR);
                return new View(map, WebPages.REGISTER, configuration);
            }
        }
        catch (SQLException ex) {
            throw ex;
        }


    }

    public View forwardForgotPassword() {

        Map map = new HashMap();

        map.put(Tags.EMAIL_ERROR, "");
        return new View(map, WebPages.FORGOT_PASSWORD, configuration);

    }

    public View getSecurityQuestion(String email) throws SQLException {
        Map map = new HashMap();
        String securityQuestion = null;

        securityQuestion = userManager.getSecurityQuestion(email);

        if (securityQuestion == null) {
            map.put(Tags.EMAIL_ERROR, AuthenticationMessages.EMAIL_NOT_REGISTERED);
            return new View(map, WebPages.FORGOT_PASSWORD, configuration);

        }
        else {

            map.put(Tags.RECOVERY_ERROR, "");
            map.put(Tags.EMAIL, email);
            map.put(Tags.SECURITY_QUESTION, securityQuestion);
            return new View(map, WebPages.FORGOT_PASSWORD_QUESTION, configuration);
        }



    }

    public View recoverPassword(String email, String securityAnswer) throws SQLException {
        Map map = new HashMap();
        String password = null;


        password = userManager.recoverPassword(email, securityAnswer);



        if (password != null) {
            map.put(Tags.PASSWORD, password);
            return new View(map, WebPages.PASSWORD, configuration);

        }
        else {
            String securityQuestion = null;

            securityQuestion = userManager.getSecurityQuestion(email);


            map.put(Tags.RECOVERY_ERROR, AuthenticationMessages.RECOVERY_ERROR);
            map.put(Tags.EMAIL, email);
            map.put(Tags.SECURITY_QUESTION, securityQuestion);
            return new View(map, WebPages.FORGOT_PASSWORD_QUESTION, configuration);
        }


    }

    public void logout(HttpServletRequest request) {
        HttpSession session = request.getSession();
        if (session != null) {
            String userId = getSessionUserId(request);
            if (userId != null) {
                gameManager.deleteUserTable(userId);

                session.invalidate();

            }
        }
    }

    public String getHighRankingsJSON() throws SQLException {
        LinkedList<User> highRankedUsers = null;

        highRankedUsers = userManager.getHighRankings();


        Gson gson = new Gson();
        return gson.toJson(highRankedUsers);

    }

    public View forwardEditProfile(HttpServletRequest request, boolean error) throws SQLException {

        if (hasSession(request)) {

            Map map = new HashMap();
            if (error)
                map.put(Tags.EDIT_PROFILE_ERROR, AuthenticationMessages.EDIT_PROFILE_ERROR);

            map.put(Tags.EDIT_PROFILE_ERROR, "");

            return new View(map, WebPages.EDIT_PROFILE, configuration);

        }

        return forwardHome(request, false);

    }

    public View editProfile(String email, String password, String firstName, String lastName, Date birthdate,
            String securityQuestion, String securityAnswer, HttpServletRequest request) throws SQLException {

        if (hasSession(request)) {
            String userId = getSessionUserId(request);
            boolean success = userManager.editProfile(email, password, firstName, lastName, birthdate, securityQuestion, securityAnswer, userId);
            if (success) {
                return new View(null, WebPages.SUCCESSFUL_EDIT, configuration);
            }
            else
                return forwardEditProfile(request, true);
        }
        return forwardHome(request, false);
    }

    public String getUserInformation(HttpServletRequest request) throws SQLException {

        String userId = getSessionUserId(request);
        User user = null;

        user = userManager.getUserById(userId);

        Gson gson = new Gson();
        String userJson = gson.toJson(user);
        return userJson;
    }

    //-----------------------Private functions---------------------
    private boolean hasSession(HttpServletRequest request) {
        String userId = getSessionUserId(request);
        if (userId != null)
            return true;


        return false;


    }

    private void createSession(HttpServletRequest request, String userId) {
        HttpSession session = request.getSession(true);
        session.setAttribute(SessionAttributes.USER_ID, userId);


    }

    private String getSessionUserId(HttpServletRequest request) {
        HttpSession session = request.getSession();
        String userId = (String) session.getAttribute(SessionAttributes.USER_ID);
        return userId;
    }

    private boolean isGuestId(String userId) {
        if (userId.length() <= SessionAttributes.GUEST_ID.length()) {
            return false;
        }
        String temp = userId.substring(0, SessionAttributes.GUEST_ID.length());
        if (temp.equals(SessionAttributes.GUEST_ID))
            return true;
        return false;
    }
}
